#pragma once
#include "Timestamp.h"
#include "noncopyable.h"

#include <functional>
#include <memory>

class EventLoop;
/**
 *
 * 封装了sockfd和感兴趣的event,如EPOLLIN, EPOLLOUT等。
 * Eventloop、Channel、Poller之间的关系是： <<=对应Reactor模型上的Demutiplex
 *  Eventloop负责管理Channel和Poller，Channel负责处理具体的事件，
 *  Poller负责具体的事件通知机制。
 *  Channel类用于表示一个网络通道，封装了事件处理和回调函数。
 * */
class Channel : mymuduo::noncopyable {
public:
  using EventCallback = std::function<void()>;
  using ReadEventCallback = std::function<void(Timestamp)>;

  Channel(EventLoop *loop, int fd);
  ~Channel();

  // fd获得poller的通知后，处理事件的函数
  void handleEvent(Timestamp receiveTime);

  // 设置回调函数
  void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); }
  void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
  void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
  void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }

  // 绑定一个对象，防止回调函数访问无效内存
  void tie(const std::shared_ptr<void> &);

  int fd() const { return fd_; }                  // 获取fd
  int events() const { return events_; }          // 获取感兴趣的事件
  void set_revents(int revt) { revents_ = revt; } // 设置Poller返回的事件

  //   设置fd相应的事件状态
  void enableReading() {
    events_ |= kReadEvent;
    update();
  }
  void disableReading() {
    events_ &= ~kReadEvent;
    update();
  }
  void enableWriting() {
    events_ |= kWriteEvent;
    update();
  }
  void disableWriting() {
    events_ &= ~kWriteEvent;
    update();
  }
  void disableAll() {
    events_ = kNoneEvent;
    update();
  }
  //   返回fd相应的事件状态
  bool isReading() const { return events_ & kReadEvent; }
  bool isWriting() const { return events_ & kWriteEvent; }
  bool isNoneEvent() const { return events_ == kNoneEvent; }

  // 获取当前的事件状态
  int index() const { return index_; }
  void set_index(int idx) { index_ = idx; }
  EventLoop *ownerLoop() { return loop_; } // 获取所属的EventLoop

  void remove();

private:
  static const int kNoneEvent;  // 无事件
  static const int kReadEvent;  // 读事件
  static const int kWriteEvent; // 写事件

  EventLoop *loop_; // 所属的EventLoop
  const int fd_;    // fd,Poller监听的文件描述符
  int events_;      // 当前感兴趣的事件
  int revents_;     // poller返回的具体发生的事件
  int index_;       // 在Poller中的索引

  std::weak_ptr<void> tie_; // 用于防止Channel被销毁时，回调函数访问无效内存
  bool tied_; // 是否绑定了一个对象，防止回调函数访问无效内存

  ReadEventCallback readCallback_; // 读事件回调函数
  EventCallback writeCallback_;    // 写事件回调函数
  EventCallback closeCallback_;    // 关闭事件回调函数
  EventCallback errorCallback_;    // 错误事件回调函数

  void update(); // 更新Channel到Poller中
  void
  handleEventWithGuard(Timestamp receiveTime); // 处理事件的函数，带有锁保护
};